package repositories

import (
	"context"
	"github.com/pkg/errors"
	"go.didapinche.com/foundation/plat-echo/app/ops/models"
	"gorm.io/gorm"
)

type DashboardRepository interface {
	Create(ctx context.Context, dashboard *models.Dashboard) error
	FindAll(ctx context.Context) ([]*models.Dashboard, error)
	Update(ctx context.Context, dashboard *models.Dashboard) error
	DeleteByID(ctx context.Context, ID uint64) error
	FindByID(ctx context.Context, ID uint64) (*models.Dashboard, error)
	FindByParentID(ctx context.Context, ID uint64) ([]*models.Dashboard, error)
	FindByName(ctx context.Context, name string, page int, size int) ([]*models.Dashboard, int64, error)
}

type dashboardRepository struct {
	db *gorm.DB
}

func NewDashboardRepository(db *gorm.DB) DashboardRepository {
	return &dashboardRepository{
		db: db,
	}
}

func (d *dashboardRepository) Create(ctx context.Context, dashboard *models.Dashboard) error {
	if err := d.db.WithContext(ctx).Table(models.DashboardTableName).Create(dashboard).Error; err != nil {
		return errors.Wrap(err, "create dashboard error")
	}
	return nil
}

func (d *dashboardRepository) FindAll(ctx context.Context) (result []*models.Dashboard, err error) {
	if err := d.db.WithContext(ctx).Table(models.DashboardTableName).Where("parent_id = 0").Find(&result).Error; err != nil {
		return nil, errors.Wrap(err, "find all dashboard error")
	}
	return result, nil
}

func (d *dashboardRepository) FindByName(ctx context.Context, name string, page int, size int) (result []*models.Dashboard, count int64, err error) {
	db := d.db.WithContext(ctx).Table(models.DashboardTableName).Where("parent_id = 0")
	if len(name) > 0 {
		db = db.Where("name like ?", "%"+name+"%")
	}
	if err := db.Count(&count).Limit(size).Offset((page - 1) * size).Scan(&result).Error; err != nil {
		return nil, 0, errors.Wrap(err, "find by name error")
	}
	return result, count, nil
}

func (d *dashboardRepository) Update(ctx context.Context, dashboard *models.Dashboard) error {
	if err := d.db.WithContext(ctx).Table(models.DashboardTableName).Save(dashboard).Error; err != nil {
		return errors.Wrap(err, "update dashboard error")
	}
	return nil
}

func (d *dashboardRepository) DeleteByID(ctx context.Context, ID uint64) error {
	if err := d.db.WithContext(ctx).Table(models.DashboardTableName).Delete(models.Dashboard{}, "id = ?", ID).Error; err != nil {
		return errors.Wrap(err, "delete dashboard error")
	}
	return nil
}

func (d *dashboardRepository) FindByID(ctx context.Context, ID uint64) (*models.Dashboard, error) {
	var dashboard = new(models.Dashboard)
	if err := d.db.WithContext(ctx).Table(models.DashboardTableName).Where("id = ?", ID).First(&dashboard).Error; err != nil {
		return nil, errors.Wrap(err, "find  dashboard id error")
	}
	return dashboard, nil
}

func (d *dashboardRepository) FindByParentID(ctx context.Context, ID uint64) (result []*models.Dashboard, err error) {
	if err := d.db.WithContext(ctx).Table(models.DashboardTableName).Where("parent_id = ?", ID).Find(&result).Error; err != nil {
		return nil, errors.Wrap(err, "FindByParentID error")
	}
	return result, nil
}
